package com.lyc.speechtranscriber

import android.annotation.SuppressLint
import android.content.Context
import android.media.AudioRecord
import android.os.Handler
import android.os.HandlerThread
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONException
import com.alibaba.idst.nui.AsrResult
import com.alibaba.idst.nui.Constants
import com.lyc.speechtranscriber.bean.HdAudioSource
import com.lyc.speechtranscriber.bean.JsonRootBean
import com.lyc.speechtranscriber.bean.MediaProjectionProvider

@SuppressLint("SetTextI18n")
class NuiSdkClient {
    private var speechTranscriber: SpeechTranscriber? = null
    private var listener: TranscriberAnalysisListener? = null
    private var mRecordingListener: RecordingListener? = null
    private val mHandler: Handler
    private var mHandlerThread: HandlerThread = HandlerThread("client_thread")
    private var mAudioSource: HdAudioSource = HdAudioSource.MIC

    constructor(){
        mHandlerThread.start()
        mHandler = Handler(mHandlerThread.looper)
    }
    companion object {
        private var instance: NuiSdkClient? = null
            get() {
                if (field == null) {
                    field = NuiSdkClient()

                }
                return field
            }
        private var attribute: TranscriberAttribute? = null
            get() {
                if (field == null) {
                    field = TranscriberAttribute()

                }
                return field
            }
        fun get(): NuiSdkClient{
            //这里不用getInstance作为为方法名，是因为在伴生对象声明时，内部已有getInstance方法，所以只能取其他名字
            return instance!!
        }

        fun getTranscriberAttribute(): TranscriberAttribute{
            return attribute!!
        }
    }

    fun createTranscriber(
        context: Context,
        aliToken: String,
        appKey: String,
        attribute: TranscriberAttribute? = null,
    ): Boolean{
        var isNew = false
        if(speechTranscriber == null){
            isNew = true
            speechTranscriber = SpeechTranscriber(context)
            speechTranscriber?.setTranscriberListener(object : TranscriberListener{
                override fun callback(
                    event: Constants.NuiEvent?,
                    result: AsrResult?,
                ) {
                    val resultContent = if(result != null){
                        var text = result.asrResult
                        try {
                            val json = JSON.parseObject(result.asrResult, JsonRootBean::class.java)
                            if(json != null){
                                if(json.payload == null){
                                    listener?.onEventAsrError(text)
                                    return
                                }
                                text = json.payload.result?:""
                            }
                        } catch (e: JSONException) {
                            e.printStackTrace()
                        }
                        text
                    }else{
                        ""
                    }


                    when (event) {
                        Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE -> {
                            listener?.onEventTranscriberComplete()
                        }
                        Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT -> {
                            if(!resultContent.isNullOrEmpty()){
                                listener?.onEventAsrPartialResult(resultContent)
                            }
                        }
                        Constants.NuiEvent.EVENT_SENTENCE_END -> {
                            if(!resultContent.isNullOrEmpty()){
                                listener?.onEventSentenceEnd(resultContent)
                            }
                        }
                        Constants.NuiEvent.EVENT_ASR_ERROR -> {
                            listener?.onEventAsrError(resultContent)
                        }
                        Constants.NuiEvent.EVENT_DIALOG_EX -> {
                            listener?.onEventDialogEx(resultContent)
                        }
                    }
                }

                override fun onNuiAudioRMSChanged(v: Float) {
                    listener?.onNuiAudioRMSChanged(v)
                }

            })

        }
        speechTranscriber?.let {
            it.setAudioSource(mAudioSource)
            it.setRecordingListener(mRecordingListener)
            it.setAliToken(aliToken)
            it.setAppKey(appKey)
            attribute?.let { mAttribute ->
                it.setMaxSentenceSilence(mAttribute.silenceTime)
                it.setEnablePunctuation(mAttribute.isEnable)
                it.setMediaProjectionProvider(mAttribute.mediaProjectionProvider)
            }
            if(isNew && !it.doInit()){
                //初始化失败
                speechTranscriber = null
                return false
            }

            it.setParams()
        }

        return true
    }

    fun setListener(listener: TranscriberAnalysisListener) {
        this.listener = listener
    }
    fun setRecordingListener(mRecordingListener: RecordingListener){
        this.mRecordingListener = mRecordingListener
    }

    fun isRecording(): Boolean {
        speechTranscriber?.let {
            return it.isRecording
        }
        return false
    }

    fun start(){
        speechTranscriber?.startDialog()
    }

    fun stop(){
        speechTranscriber?.stopDialog()
    }

    fun release(){
        speechTranscriber?.release()
        speechTranscriber = null
    }

    fun setAudioSource(audioSource: HdAudioSource) {
        mAudioSource = audioSource
        speechTranscriber?.setAudioSource(audioSource)
    }

    class TranscriberAttribute{
        var silenceTime = 800
        var isEnable = true
        var mediaProjectionProvider: MediaProjectionProvider? = null

        fun setMaxSentenceSilence(silenceTime: Int): TranscriberAttribute{
            this.silenceTime = silenceTime
            return this
        }

        fun setEnablePunctuation(isEnable: Boolean): TranscriberAttribute{
            this.isEnable = isEnable
            return this
        }

        fun setMediaProjectionProvider(mediaProjectionProvider: MediaProjectionProvider?): TranscriberAttribute{
            this.mediaProjectionProvider = mediaProjectionProvider
            return this
        }
    }
}